#include "DXUT.h"
#include "Frustum.h"


CFrustum::CFrustum(void)
{
}


CFrustum::~CFrustum(void)
{
}

void CFrustum::CalculateFrustum( const D3DXMATRIX * view,  const D3DXMATRIX *projection )
{
 
		 
		D3DXMATRIX matComb;
		D3DXMatrixMultiply(&matComb, view, projection);

	 
		m_frustum[0].a = matComb._14 + matComb._11; 
		m_frustum[0].b = matComb._24 + matComb._21; 
		m_frustum[0].c = matComb._34 + matComb._31; 
		m_frustum[0].d = matComb._44 + matComb._41;

	 
		m_frustum[1].a = matComb._14 - matComb._11; 
		m_frustum[1].b = matComb._24 - matComb._21; 
		m_frustum[1].c = matComb._34 - matComb._31; 
		m_frustum[1].d = matComb._44 - matComb._41;

	 
		m_frustum[2].a = matComb._14 - matComb._12; 
		m_frustum[2].b = matComb._24 - matComb._22; 
		m_frustum[2].c = matComb._34 - matComb._32; 
		m_frustum[2].d = matComb._44 - matComb._42;

	 
		m_frustum[3].a = matComb._14 + matComb._12; 
		m_frustum[3].b = matComb._24 + matComb._22; 
		m_frustum[3].c = matComb._34 + matComb._32; 
		m_frustum[3].d = matComb._44 + matComb._42;
 
		m_frustum[4].a = matComb._13; 
		m_frustum[4].b = matComb._23; 
		m_frustum[4].c = matComb._33; 
		m_frustum[4].d = matComb._43;

		 
		m_frustum[5].a = matComb._14 - matComb._13; 
		m_frustum[5].b = matComb._24 - matComb._23; 
		m_frustum[5].c = matComb._34 - matComb._33; 
		m_frustum[5].d = matComb._44 - matComb._43; 

	 
		for(int i=0;i<6;i++)
			D3DXPlaneNormalize(&m_frustum[i], &m_frustum[i]);
 
}

bool CFrustum::Cull( BoundingBox * bBox )
{ 
	
 
		for(int f=0;f<6;f++)
		{
			D3DXVECTOR3 c1, c2;

			 
			if(m_frustum[f].a > 0.0f)	{c1.x = bBox->max.x; c2.x = bBox->min.x;}
			else					{c1.x = bBox->min.x; c2.x = bBox->max.x;}
			if(m_frustum[f].b > 0.0f)	{c1.y = bBox->max.y; c2.y = bBox->min.y;}
			else					{c1.y = bBox->min.y; c2.y = bBox->max.y;}
			if(m_frustum[f].c > 0.0f)	{c1.z = bBox->max.z; c2.z = bBox->min.z;}
			else					{c1.z = bBox->min.z; c2.z = bBox->max.z;}

			float distance1 = m_frustum[f].a * c1.x + m_frustum[f].b * c1.y + 
				m_frustum[f].c * c1.z + m_frustum[f].d;
			float distance2 = m_frustum[f].a * c2.x + m_frustum[f].b * c2.y + 
				m_frustum[f].c * c2.z + m_frustum[f].d;

		 
			if(distance1 < 0.0f && distance2 < 0.0f)
				return true;
		}
	 
		return false;
 



	//for( char p = 0; p < 5; p++ )
	//{
	//	if( D3DXPlaneDotCoord( &m_frustum[p], &D3DXVECTOR3( bBox->min.x, bBox->min.y, bBox->min.z ) ) >= 0.0f )
	//		continue;
	//	if( D3DXPlaneDotCoord( &m_frustum[p], &D3DXVECTOR3( bBox->max.x, bBox->min.y, bBox->min.z ) ) >= 0.0f )
	//		continue;
	//	if( D3DXPlaneDotCoord( &m_frustum[p], &D3DXVECTOR3( bBox->min.x,bBox-> max.y, bBox->min.z ) ) >= 0.0f )
	//		continue;
	//	if( D3DXPlaneDotCoord( &m_frustum[p], &D3DXVECTOR3( bBox->max.x, bBox->max.y, bBox->min.z ) ) >= 0.0f )
	//		continue;
	//	if( D3DXPlaneDotCoord( &m_frustum[p], &D3DXVECTOR3( bBox->min.x, bBox->min.y, bBox->max.z ) ) >= 0.0f )
	//		continue;
	//	if( D3DXPlaneDotCoord( &m_frustum[p], &D3DXVECTOR3(bBox-> max.x, bBox->min.y, bBox->max.z ) ) >= 0.0f )
	//		continue;
	//	if( D3DXPlaneDotCoord( &m_frustum[p], &D3DXVECTOR3(bBox-> min.x,bBox-> max.y, bBox->max.z ) ) >= 0.0f )
	//		continue;
	//	if( D3DXPlaneDotCoord( &m_frustum[p], &D3DXVECTOR3(bBox-> max.x, bBox->max.y,bBox-> max.z ) ) >= 0.0f )
	//		continue;

	//	return true;
	//}
	//return false;
}

bool CFrustum::Cull( BoundingSphere * bSphere )
{
	try
	{
 
		for(int f=0;f<6;f++)
		{
			float distance = D3DXVec3Dot(&bSphere->centre, &D3DXVECTOR3(m_frustum[f].a, m_frustum[f].b, m_frustum[f].c)) + m_frustum[f].d;

			if(distance < -bSphere->radius  )
				return true;
		}

 
		return false;
	}
	catch(...)
	{
	 MessageBox(0,TEXT("Error in  BoundingSphere()"),0,0);
		return true;
	}
}
